Import diddy
Import hgameimage
Import gameglobals
'don't need mouse info


Class BackdropState

	Field backdrop:BackdropData[]
	
	Method SetBackdropArray(size:Int)
	
		Local b:BackdropData[size]
		
		backdrop = b
	
	End
End

Class BackdropData

	Field filename:String
	Field img:Image

End


Class SongState

	Field music:MusicData[]

	Method SetMusicArray(size:Int)
	
		Local m:MusicData[size]
		
		music = m
	
	End

End


Class MusicData

	Field filename:String
	'Field music:Image

End



class Door
	Field x:Int, y:Int
	Field bits:Int[1]'<--- why array of one??
End

class DoorLink
	Field source:Int, dest:Int, dest_map:Int, tag1:Int, tag2:Int
End

Class MapData

	Field Mapfile:String
	Field doors:Door[]
	Field links:DoorLink[]	
	Field npcs:NPCType[]
End

Class HTileMapTileset Extends TileMapTileset Implements ITileMapPostLoad
	' attributes
	Field simage:HGameImage
	Field edsprites:SpriteSet

End

'Until i find the actual class this is temporary
Class XYPair

	Field x:Int
	Field y:int

End

Class SpriteType Abstract
	Const sprTypeInvalid = -1
	Const sprTypeHero = 0
	Const sprTypeSmallEnemy = 1
	Const sprTypeMediumEnemy = 2
	Const sprTypeLargeEnemy = 3
	Const sprTypeWalkabout = 4
	Const sprTypeWeapon = 5
	Const sprTypeAttack = 6
	Const sprTypeBoxBorder = 7
	Const sprTypePortrait = 8
	Const sprTypeLastPT = 8
	Const sprTypeMXS = 9    'Can't change this! Saved in .slice files
	Const sprTypeLast = 9   'Last sprite type selectable in slice editor
	Const sprTypeFrame = 10  'A sprite not loaded from file, but from a Frame. Free to change this later (never saved)
End

class Palette256
	Field col:Int[256] 'monkey uses int for color data
	Field refcount:Int 'private
	
	Method DefaultPalette()
	
		For Local i:Int = 0 To 255
			If i = 0 Then
				col[i] = 0
				'first palette is always blank
			Else
				col[i] = ToARGB(255,Rnd(0,255),Rnd(0,255),Rnd(0,255))
			Endif
			
		next
	
	End

	method IntToRGBA:Int[]( Value:Int )
		Local rgba:Int[4]
		rgba[3] = ( Value Shr 24 ) & $FF
		rgba[0] = ( Value Shr 16) & $FF
		rgba[1] = ( Value Shr 8) & $FF
		rgba[2] = Value & $FF
		Return rgba
	End


	Method ToARGB:Int(a:Int,r:Int,g:Int,b:Int)
		Local argb:Int = (a Shl 24) | (r Shl 16) | (g Shl 8) | b
		'Local argb:Int = (r Shl 16) | (g Shl 8) | b
		Return argb
	End
	
End

'not sure when i'll need these

'TYPE SpriteCacheEntryFwd as SpriteCacheEntry
'TYPE SpriteSetFwd as SpriteSet


Class Frame


	Field w:int
	Field h:int
	Field pitch:int     'pixel (x,y) is at .image[.x + .pitch * .y]; mask and image pitch are the same!
	Field image:HGameImage 'not sure if i should use diddy GameImage or simply Image as ubyte ptr
	Field refname:String
	'Field mask:Int[3] 'This may be obsolete since monkey uses alpha channels.. as ubyte ptr
	Field refcount:Int ' as integer  'see frame_unload in particular for documentation
	Field arraylen:Int ' as integer  'how many frames were contiguously allocated in this frame array
	Field base:Frame ' as Frame ptr    'the Frame which actually owns this memory
	Field cacheentry:int 'Monkey has some builtin precache functions so i need to lookinto it before i dabble further... as SpriteCacheEntryFwd ptr
	
	'i will need a pixmap of the image using array indexes, this will make it easy to swap pixel colors when the palette changes.
	Field PixMap:Int[]
	'Field cached:1 as integer  '(not set for views onto cached sprites)
	'arrayelem:1 as integer  'not the first frame in a frame array
	'isview:1 as integer

	'used only by frames in a SpriteSet, for now
	Field offset:XYPair 'CHANGE TO XYPAIR
	'sprset as SpriteSetFwd ptr  'if not NULL, this Frame array is part of a SpriteSet which
	
	Method WritePixMap(x:Int,y:Int,id:Int)
	
		PixMap[x+(y*w)] = id
	
	End

	Method Redraw(pal:Palette256,nx:Int=0,ny:Int=0)
	
		Local pmap:Int[w*h]
		For Local yy:Int = 0 To h-1
			For Local xx:Int = 0 To w-1
				'Print "debug: color:"+PixMap[xx+(yy*w)]
				pmap[xx+(yy*w)] = pal.col[PixMap[xx+(yy*w)]]
			Next
		Next
		image.image.WritePixels( pmap, nx, ny, w, h)
	End

	
	Method Clone:Frame()
		'Print "Clone Frame: w: "+w+" h: "+h+" name: "+refname
		
		Local f:Frame = New Frame(w,h,refname+"_clone")
		For Local i:Int = 0 To PixMap.Length-1
		
			f.PixMap[i] = PixMap[i]
		
		Next
		
		Return f
		
	
	End
	
	
	Method New(ww:Int,hh:Int,nname:String="Myimg_"+Rnd()+""+ww+"x"+hh,mr:Int = 0,mg:Int = 0,mb:Int = 0)
		'Print "Create new frame: w "+ww+" h "+hh
		w = ww
		h = hh
		refname = nname
		image = New HGameImage 
		image.HLoad(CreateImage(w,h),nname,True,True,mr,mg,mb,False)'
		Local pmap:Int[ww*hh]
		PixMap = pmap
		'mask = New GameImage
		'mask.image = CreateImage(w,h) 'LoadImage(diddyGame.images.path + "tmpspr.png")
	End    
    
                                    'will need to be freed at the same time
End

Class AnimOpType Abstract
	Const animOpWait = 1	'(ticks)
	Const animOpFrame = 2	'(framenum)
	Const animOpSetOffset = 3	'(x,y)
	Const animOpRelOffset = 4	'(x,y)
end

class AnimationOp
	Field type:AnimOpType
	Field arg1:int		
	Field arg2:int	
end

class Animation
	Field name:String
	Field numitems:int
	Field ops:AnimationOp
end




Class BackdropSet
	Field name:String
	Field id:String
	Field frame:Image
End


Class SpriteSet
	Field anim:GameImage
	Field numanimations:Int
	Field animations:Animation
	Field numframes:int  'redundant to frames->arraylen
	Field frames:Frame[]
	Field palid:int
	'uses refcount from frames
	
	
	Method CloneSpriteSet:SpriteSet()
	
		Local source:SpriteSet = New SpriteSet
		source.numanimations = numanimations
		source.numframes = numframes
		source.palid = palid
		'Print "Clone Spriteset with frames: "+numframes+" and arraylen of "+frames.Length
		Local f:Frame[frames.Length]
		source.frames = f
		For Local i:Int = 0 To frames.Length-1
		
			source.frames[i] = frames[i].Clone()
		
		Next
		
		
		Return source
		
	
	End
	
	Method RedrawFrames(pal:Palette256)
	
		For Local i:Int = 0 To frames.Length-1
			frames[i].Redraw(pal)
		Next
	
	End
	
	Method SetFrames(nof:Int,w:Int,h:Int,nname:String="msst"+Rnd+"_",mr:Int=0,mg:Int=0,mb:Int=0)
		'Print "Set Frames with w: "+w+" h: "+h+" count: "+nof
		Local f:Frame[nof]
		For Local i:Int = 0 To nof-1
			f[i] = New Frame(w,h,nname+i,mr,mg,mb)
		Next
		frames = f
	End
	
End

'A REAL sprite; This is basically a SpriteSet object with state
'Not refcounted. I don't currently see a reason that it should be (each the state of a single object)
'WARNING: don't add strings to this
'WARNING: foo! i do what i want!
class SpriteState
	Field set:SpriteSet
	Field curframe:Frame  'convenience ptr to set->frames[.frame_id]
	Field pal:Palette256
	Field frame_id:int
	Field anim:Animation
	Field anim_step:int
	Field anim_wait:int
	Field anim_loop:int  '-1:infinite, 0<:number of times to play after current
	Field offset:XYPair
	Field derp:String
End

class GraphicPair
	Field sprite:Frame
	Field pal:palette256
End

class ClipState
	Field whichframe:Frame
	Field clipl:Int' as integer
	Field clipr:Int' as integer
	Field clipt:Int' as integer
	Field clipb:Int' as integer
End

class MenuSet
  Field menufile:String
  Field itemfile:String
end

Class BasicMenuItem
  Field text:String
  Field col:int
  Field bgcol:int
  Field unselectable:Bool
  Field disabled:Bool  'Appear greyed out. Any other meaning of this is up to the user
End

'DECLARE_VECTOR_OF_TYPE(BasicMenuItem, BasicMenuItem)
'MAKETYPE_DoubleList(MenuDefItem)
'MAKETYPE_DListItem(MenuDefItem)

class MenuDefItem extends BasicMenuItem
  'members copied from BasicMenuItem

  'Other members
  Field handle:Int'    as integer
  Field caption:String'   as String  ' This is the caption as set in the menu editor/set menu item caption
  Field trueorder:=New List<MenuDefItem>' as DListItem(MenuDefItem) ' contains next, prev
  Field t:Int'         as integer
  Field sub_t:Int'     as integer
  Field tag1:Int'      as integer
  Field tag2:Int'      as integer
  Field settag:Int'    as integer
  Field togtag:Int'    as integer
  Field extra:Int[2]'  as integer
  Field hide_if_disabled:Bool'  as Bool
  Field close_if_selected:Bool' as Bool
  Field skip_close_script:Bool' as Bool
  Field dataptr:Object 'seems monkey lacks a catch all pointer   as any ptr  'Use this with caution!
End


class MenuDef
  Field record:Int'    as integer
  Field handle:Int'    as integer
  Field name:String'      as String
  Field boxstyle:Int'  as integer
  Field textcolor:Int' as integer
  Field maxrows:Int'   as integer
  Field edit_mode:Bool' as Bool   'Never hide disabled items, allow selection of unselectable items
  Field items:MenuDefItem'     as MenuDefItem Ptr Ptr
  'adds first, last, numitems, itemlist members
  'Field INHERITAS_DoubleList(MenuDefItem, itemlist) ' <- Come back to this one.....True order of menu items, ignoring sort-invisible-items-to-end
  Field translucent:Bool'      as Bool ' Bitset 0
  Field no_scrollbar:Bool'     as Bool ' Bitset 1
  Field allow_gameplay:Bool'   as Bool ' Bitset 2
  Field suspend_player:Bool'   as Bool ' Bitset 3
  Field no_box:Bool'           as Bool ' Bitset 4
  Field no_close:Bool'         as Bool ' Bitset 5
  Field no_controls:Bool'      as Bool ' Bitset 6
  Field prevent_main_menu:Bool' as Bool ' Bitset 7
  Field advance_textbox:Bool'  as Bool ' Bitset 8
  Field highlight_selection:Bool' as Bool 'Bitset 9
  Field rect:RectType'      as RectType
  Field offset:XYPair'    as XYPair
  Field anchor:XYPair'    as XYPair
  Field align:Int'     as integer
  Field min_chars:Int' as integer
  Field max_chars:Int' as integer
  Field bordersize:Int' as integer
  Field itemspacing:Int' as integer 'pixels added to the default item spacing.
                          'negative shrinks, positive grows. This
                          'alters the vertical size of the whole menu!
  Field on_close:Int'  as integer 'script trigger
  Field esc_menu:Int'  as integer
  
  'Declare Destructor () 'defined in menus.bas
end

Class MenuState
  Field active:Bool'    as Bool = YES
  Field pt:Int'        as integer 'currently selected item (.first - 1 if menu is empty)
  Field top:Int'       as integer 'scroll position for long lists
  Field first:Int'     as integer 'first element (usually zero)
  Field last:Int'      as integer 'last element (.first - 1 if menu is empty)
  Field size:Int'      as integer 'number of elements to display at a time - 1
  Field need_update:Bool' as Bool  'menu needs some kind of update
  Field tog:int'       as Bool    'For flashing cursor
  '--populated when the menu is drawn
  Field has_been_drawn:Bool' as Bool
  Field rect:RectType' as RectType
  Field spacing:Int' as integer
end
#rem
'A set of rendering options which can be passed to standardmenu.
'This partially overlaps MenuDef, which is the reason it wasn't added to MenuState:
'MenuState is used for drawing MenuDefs too, which would be confusing
TYPE MenuOptions
  edged as bool
  wide as integer = 9999
  highlight as bool
  showright as bool       'Always show the right-most portion of text if too long,
                          'instead of only doing so when selected.
  scrollbar as bool       'Draw a scrollbar (boxstyle 0); position given by x, y, .wide and MenuState.size
  fullscreen_scrollbar as bool 'Draw a scrollbar at the right edge of the screen
END TYPE

'For when a string array is too crude, but a MenuDef is overkill
TYPE SimpleMenuItem  'EXTENDS BasicMenuItem
  'members copied from BasicMenuItem
  text as string
  col as integer
  bgcol as integer
  unselectable as bool
  disabled as bool  'Appear greyed out. Other meaning of this depend on use 

  'other members
  dat as integer  'For your own use
END TYPE
DECLARE_VECTOR_OF_TYPE(SimpleMenuItem, SimpleMenuItem)

'This type abstracts menu data (either a string array or a BasicMenuItem-derived vector)
'and a search method for select_by_typing.
'(The menu length must not change during the lifetime of this object!)
TYPE MenuSearcher
 'Get the text of a menu item
 'getfunc as function(this as MenuSearcher, byval index as integer) as string
 'Search text for a query and return position in the text of a match, or 0 for no match
 findfunc as function(this as MenuSearcher, itemtext as string, query as string) as integer

 'Exactly one of the following is non-null
 menu_array as string ptr
 menu_vector as BasicMenuItem vector

 excludeword as string      'used only by MenuSearcher_find_word_boundary

 declare Constructor(menu() as string)
 declare Constructor(menu_vector as BasicMenuItem vector)
 declare function text(byval index as integer) as string
 declare function selectable(byval index as integer) as bool
END TYPE

TYPE SelectTypeState
 query as string              'String to search for
 buffer as string             'Text the user has entered
 last_input_time as double    'TIMER at last input

 'Used by highlight_menu_typing_selection
 query_at as integer          'Offset in text of current menu item of match, or 0
 highlight_at as integer      'Offset of match/no match text highlighting. Remembers last non-zero value of query_at.
 'highlight_pt as integer      'Menu index (line) where the highlighting is. Is different from state.pt only if unselectable
 remember_pt as integer       'Remember last state.pt value
END TYPE


'Warning: when editing NPCType, consider updating read/write_npc_int and serialization disasters
'including updating readnpc, alternpc, plotscr.hsd constants, and plotdict.xml
TYPE NPCType
  picture as integer     '+0
  palette as integer     '+1
  movetype as integer    '+2
  speed as integer       '+3  real speed, not value in .d
  textbox as integer     '+4
  facetype as integer    '+5
  item as integer        '+6
  pushtype as integer    '+7
  activation as integer  '+8
  tag1 as integer        '+9   appear only if
  tag2 as integer        '+10  appear only if 2
  usetag as integer      '+11  onetime use bit or 0 for none
  script as integer      '+12
  scriptarg as integer   '+13
  vehicle as integer     '+14
  defaultzone as integer '+15
  defaultwallzone as integer '+16
  sprite as frame ptr
  pal as palette16 ptr
END TYPE

'Don't forget to update CleanNPCL and load/save_npc_locations when adding to this
TYPE NPCInst
  sl as SliceFwd Ptr
  '--stored values
  x as integer      'npcl+0
  y as integer      'npcl+300
  z as integer      '            Does not include foot offset
  id as integer     'npcl+600    0 if unused, ID + 1 for normal NPCs, -ID - 1 for hidden NPCs
                    '  NOTE: NPCs with invalidly high ID numbers (on incompletely loaded maps)
                    '        are automatically hidden (and obviously unsafe to unhide)
  xgo as integer    'npcl+1500   warning: positive to go LEFT, negative RIGHT
  ygo as integer    'npcl+1800   reversed as above
  dir as integer    'npcl+900
  frame as integer  'npcl+1200   0-3: ticks in walk animation loop (2 ticks per frame)
  extra(2) as integer
  ignore_walls as bool  'ignore passmap
  not_obstruction as bool 'can walk through npcs+heroes and vice-versa
  suspend_use as bool   'not activatable 
  suspend_ai as bool    'ignore movetype (effectively 'stand still')
  curzones as integer vector  'sorted vector of zones this NPC is currently inside
END TYPE

TYPE InventSlot
  used as bool          'use this to check if empty, not num!

  'following fields should not be used if used = NO
  id as integer	        'read ID number starting at 0, not +1!!
  num as integer
  text as string        'text field which shows up in inventory, blank if empty
  sortorder as integer  'contains garbage nearly always: only used in items_menu_autosort
END TYPE

TYPE PlotTimer
  count as integer
  speed as integer
  ticks as integer
  trigger as integer
  flags as integer  '1=critical 2=battle 4=menu 8+=undefined
  st as integer     'string, but both str and string are reserved
  pause as bool
  finished_tick as integer  'tick at which this last triggered; 0 if never
END TYPE

TYPE Plotstring
  s as string
  X as integer
  Y as integer
  col as integer
  bgcol as integer
  bits as integer   '1=visible, 2=edgeless text
END TYPE

Type HSHeader
  valid as bool
  hspeak_version as string
  hsp_format as integer
  script_format as integer    'Same as the .HSZ format number, or 0 if not known
  max_function_id as integer  'Maximum ID of a used function, or 0 if not known
  plotscr_version as string   'empty if not known
End Type

TYPE TriggerData
  name as string
  id as integer
END TYPE

'WARNING: don't add strings to this
TYPE ScriptData
  id as integer         'id number of script  (set to 0 to mark as unused slot)
  refcount as integer   'number of ScriptInst pointing to this data
  totaluse as integer   'total number of times this script has been requested since loading
  lastuse as integer
  totaltime as double   'time spent in here, in seconds. Used only if SCRIPTPROFILE is defined
  entered as integer    'number of times entered. Used only if SCRIPTPROFILE is defined
  ptr as integer ptr    'pointer to script commands
  size as integer       'size of script data, in 4 byte words
  vars as integer       'variable (including arguments) count
  args as integer       'number of arguments
  strtable as integer   'pointer to string table (offset from start of script data in long ints)

  next as ScriptData ptr 'next in linked list, for hashtable
  backptr as ScriptData ptr ptr 'pointer to pointer pointing to this, in script(), or a .next pointer
                        'not your usual double linked list, because head of list is a script() element
END TYPE

TYPE ScriptInst
  scr as ScriptData ptr 'script in script() hashtable
  scrdata as integer ptr 'convenience pointer to scr->ptr
  heap as integer       'position of the script's local vars in the buffer
  stackbase as integer  'position where this script's stack data starts in scrst
  state as integer      'what the script is doing right now
  ptr as integer        'the execution pointer (in int32's from the start of the script data)
  ret as integer        'the scripts current return value
  curargn as integer    'current arg for current statement
  depth as integer      'stack depth of current script
  id as integer         'id number of current script
  waitarg as integer    'wait state argument 1
  waitarg2 as integer   'wait state argument 2
  watched as bool       'true for scripts which are being logged
  started as bool       'used only if watched is true: whether the script has started

  'these 3 items are only current/correct for inactive scripts. The active script's current
  'command is pointed to by the curcmd (ScriptCommand ptr) global, and copied here
  'when a script is stopped (either suspended, or interpretloop is left)
  curkind as integer    'kind of current statement
  curvalue as integer   'value of current statement
  curargc as integer    'number of args for current statement
END TYPE

TYPE QueuedScript
  id as integer         'Triggers pre-decoded
  scripttype as string
  trigger_loc as string 'More information about how it was triggered
  double_trigger_check as bool  'Whether to prevent double triggering
  log_line as string    'Debugging aid: Comprised from scripttype, arg names and values and trigger_loc
  argc as integer       'The number of args passed
  args(3) as integer
END TYPE

TYPE ScriptCommand
  kind as integer
  value as integer
  argc as integer
  args(999999) as integer
END TYPE

UNION RGBcolor
  as uinteger col
  TYPE
    as ubyte b, g, r, a
  END TYPE
END UNION
#end


'Type TileAnimState
'  cycle as integer 'Current tile offset (tile to show)
'  pt as integer    'Step number of the next step in the animation
'  skip as integer  'Number of ticks left in current wait
'END Type

'Type TilesetData
'  num as integer
'  spr as Frame ptr
'  anim(1) as TileAnimState
'  tastuf(40) as integer
'End Type

'*** Requires construction + destruction ***

'*** Diddy has a builtin tilemap class, we are going to subout this with Diddy and try to work around.
'*** Also supports importing maps from Tiled http://www.mapeditor.org/


Class NPCType

	Field x:Int
	Field y:Int
	Field dir:Int
	Field id:Int
	
	Field picture:Int' as integer     '+0
	Field palette:Int' as integer     '+1
	Field movetype:Int' as integer    '+2
	Field speed:Int' as integer       '+3  real speed, not value in .d
	Field textbox:Int' as integer     '+4
	Field facetype:Int' as integer    '+5
	Field item:Int' as integer        '+6
	Field pushtype:Int' as integer    '+7
	Field activation:Int' as integer  '+8
	Field tag1:Int' as integer        '+9   appear only if
	Field tag2:Int' as integer        '+10  appear only if 2
	Field usetag:Int' as integer      '+11
	Field script:Int' as integer      '+12
	Field scriptarg:Int' as integer   '+13
	Field vehicle:Int' as integer     '+14
	Field defaultzone:Int' as integer '+15
	Field defaultwallzone:Int' as integer '+16
	Field sprite:Frame' as frame Ptr
	Field pal:Palette256' as palette16 Ptr
	Field valdata:Int[18]
	Field sprites:SpriteSet
End



Class HTileMap Extends TileMap

	Field tname:String
	Field doors:Door[]
	Field links:DoorLink[]
	Field npcs:NPCType[]
	Field currentdoorcol:int
	Field entrydoorcol:bool = False
	Method SetDoors(d:Door[],dl:DoorLink[])	
		
		doors = d
		links = dl
		
		
	End


	
	Method RenderNPCS:Void(offsetx:Int,offsety:Int,sw:Int,sh:int)
	' bx,by,bw,bh = render bounds (screen)
	' sx,sy = scale x/y (float, defaults to 1) i'll do this later
	' wx,wy = wrap x/y (boolean, defaults to false)		
	'draw npcs
		
		For Local i:Int = 0 To npcs.Length-1

			DrawImage(npcs[i].sprites.frames[npcs[i].dir].image.image,(npcs[i].x+(npcs[i].sprites.frames[npcs[i].dir].image.w/2))-offsetx,(npcs[i].y-(npcs[i].sprites.frames[npcs[i].dir].image.h/2))-offsety)
		
		Next
		
	
	End	
	
	Method LoadNPCS(n:NPCType[])
	
		npcs = n
		Print "Loading NPCS: "+npcs.Length
		For Local i:Int = 0 To npcs.Length-1
		
			If npcs[i].sprites = Null Then
				npcs[i].sprites = WalkaboutSpr[npcs[i].picture].CloneSpriteSet
				
				npcs[i].sprites.RedrawFrames(Palettes[npcs[i].palette])
				
			Endif
		
		
		Next
	
	End
	
	Method HideColLayers()
		Local layer:TileMapTileLayer
		For Local tl:TileMapLayer = Eachin layers
			If TileMapTileLayer(tl)
				 
				If tl.name.Find("collision") <> -1 Or  tl.name.Find("enemy") <> -1 Then 
					tl.visible = false
				Endif
				'layer = TileMapTileLayer(tl) ; Exit
			Endif
		Next	
	end

	Method GetDoorLink:int(doorid:Int)
	
		For Local i:Int = 0 To links.Length-1
		
			If links[i].source = doorid Then
				Return i
			Endif
		Next
		Return -1
	End

	Method RenderDoors:Void(offsetx:Int,offsety:Int,sw:Int,sh:int)
	' bx,by,bw,bh = render bounds (screen)
	' sx,sy = scale x/y (float, defaults to 1) i'll do this later
	' wx,wy = wrap x/y (boolean, defaults to false)		
	'draw npcs
		
		For Local i:Int = 0 To doors.Length-1

			SetColor(255,255,255)
			DrawRect((doors[i].x*tileWidth)-offsetx,((doors[i].y-1)*tileHeight)-offsety,20,20)
			'DrawImage(npcs[i].sprites.frames[npcs[i].dir].image.image,(npcs[i].x+(npcs[i].sprites.frames[npcs[i].dir].image.w/2))-offsetx,(npcs[i].y-(npcs[i].sprites.frames[npcs[i].dir].image.h/2))-offsety)
		
		Next
		
	
	End	

	Method DoorCollision:Int(playerx%, playery%, playerw%, playerh%, offx%, offy%)

		playerx=playerx+offx
		playery=playery+offy
		Local gx%, gy%, gw%, gh%
		gx = (playerx / tileWidth) 
		gy = (playery / tileHeight) 
		gw = (playerw / tileWidth) 
		gh = (playerh / tileHeight) 
		
		

		Local coll:Int=0
		For Local y:= gy To gy+gh
			If coll Then Exit
			If y<0 Or y>height Then Continue
			For Local x:= gx To gx+gw
				If x<0 Or x>width Then Continue
				For Local i:Int = 0 To doors.Length-1
		
					If doors[i].x = x And doors[i].y-1 = y Then
						currentdoorcol = i
						coll=1
						exit
					endif
		
				Next
				
				If coll=1 Then 
					
					Exit
				Endif
			Next
		Next
			
		Return coll
	
	End

	method TileCollision:Int(layername:String, playerx%, playery%, playerw%, playerh%, offx%, offy%)
		If Not layername Or tileWidth=0 Or tileHeight=0 Return 0
	
		'' string search could be removed for faster lookups
		Local layer:TileMapTileLayer
		For Local tl:TileMapLayer = Eachin layers
			If TileMapTileLayer(tl)
				'Print tl.name
				If tl.name = layername Then 
					layer = TileMapTileLayer(tl)
					Exit
				End if
			Endif
		Next
		If layer = Null Then Return 0
		If layer.name <> layername Then Return 0
	
		
		''convert x,y,w,h to grid
		Local gx%, gy%, gw%, gh%
		
		playerx=playerx+offx
		playery=playery+offy
	
		gx = (playerx / tileWidth) 
		gy = (playery / tileHeight) 
		gw = (playerw / tileWidth) 
		gh = (playerh / tileHeight) 
	
	
		'Print gx+"+"+gy
		
		Local coll:Int=0
		For Local y:= gy To gy+(gh)-1
			If coll Then Exit
			If y<0 Or y>height Then Continue
			For Local x:= gx To gx+(gw)-1
				If x<0 Or x>width Then Continue
				If layer.mapData.Get(x,y) = 15 Then coll=1 ; Exit
			Next
		Next
		
		'If coll Then Print gx+":"+gy+" "+coll
		
		Return coll
	End
	
	Method CalcSize()
	
		For Local l:TileMapLayer = Eachin layers
			If TileMapTileLayer(l) <> Null Then
				Local tl:TileMapTileLayer = TileMapTileLayer(l)
				For Local i% = 0 Until tl.mapData.tiles.Length
					If tl.mapData.tiles[i] > 0 Then
						If tl.maxTileWidth < tiles[tl.mapData.tiles[i] - 1].width Then tl.maxTileWidth = tiles[tl.mapData.tiles[i] - 1].width
						If tl.maxTileHeight < tiles[tl.mapData.tiles[i] - 1].height Then tl.maxTileHeight = tiles[tl.mapData.tiles[i] - 1].height
					End
				Next
			End
		Next	
	End

End

'Type TileMap
'  wide as integer
'  high as integer
'  data as ubyte ptr
'  layernum as integer
'End Type

'TYPE TilemapInfo
'  wide as integer
'  high as integer
'  layers as integer
'END TYPE

'WARNING: don't add strings to this
'Type ZoneHashedSegment
'  IDmap(14) as ushort
'  hashed as HashedItem
'End Type

'Data associated with an individual zone, other than the tiles themselves
Class ZoneInfo
  Field id:Int
  Field name:String
  Field hidden:bool  'used in the map editor only, not saved
  Field numtiles:int 'number of set tiles
  Field extra:Int[2]
End

'A set of zones
'See loading.rbas for documentation.
'*** Requires construction + destruction ***

#rem
Type ZoneMap
  numzones as integer
  zones as ZoneInfo ptr
  wide as integer  'width in tiles
  high as integer  'height in tiles
  wide_segments as integer  'width in 4x4 tile segments
  high_segments as integer  'height in 4x4 tile segments
  bitmap as ushort ptr      'array dimensions are [high][wide]
  zoneIDmap as ushort ptr   'array dimensions are [high_segments][wide_segments][16]
  extraID_hash as HashTable 'table of ZoneHashedSegments for overcrowded tiles, indexed by (x SHL 16) + y
End Type

Type FontChar
	offset as integer  'offset into spr->image
	offx as byte   'pixel offsets
	offy as byte
	w as byte      'size of sprite
	h as byte
End Type

'WARNING: don't add strings to this
Type FontLayer
	spr as Frame ptr
	refcount as integer
	chdata(255) as FontChar
End Type

Type Font
	initialised as bool
	layers(1) as FontLayer ptr	'single layer fonts should use sprite(1) only
	w(255) as integer	'width of each character
	h as integer		'height of a line
	offset as XYPair	'added to coordinates when printing
	cols as integer		'number of used colours, not including colour 0 (transparency), so at most <s>255</s> 15
	pal as Palette16 ptr    '(Default) palette template to use, or NULL if this font is unpaletted (foreground colour only)
	pal_id as integer       'id of pal. Not used by render_text
	outline_col as integer  'palette entry which should be filled with uiOutline, or -1 for none
End Type

'text_layout_dimensions returns this struct
Type StringSize
	h as integer         'Height (in pixels)
	w as integer         'Greatest width of any line
	endchar as integer   'For when maxlines is specified: one character past last line
	lastw as integer     'Width of last line fragment
	lasth as integer     'Height of last line fragment
	lines as integer     'Number of lines (always at least 1)   FIXME:  not true
	finalfont as Font ptr
End Type

Type StringCharPos
	charnum as integer   'offset in string; equal to len(text) if off the end
	exacthit as bool     'whether actually on this character, or just the nearest (eg. off end of line)
	x as integer         'position is in screen coordinates
	y as integer
	'w as integer        'Size of the selected character (do we really need this?)
	h as integer
	lineh as integer     'height of containing line fragment
End Type

Type PrintStrStatePtr as PrintStrState ptr

Type Door
	as integer x, y
	as integer bits(0)
End Type

Type DoorLink
	as integer source, dest, dest_map, tag1, tag2
End Type

Union Stats
       Type
               hp as integer
               mp as integer
               str as integer
               acc as integer
               def as integer
               dog as integer
               mag as integer
               wil as integer
               spd as integer
               ctr as integer
               foc as integer
               hits as integer
       End Type
       sta(11) as integer
End Union

Type AttackDataTag
	tag as integer
	condition as integer
	tagcheck as integer
End Type

Type AttackDataItem
	id as integer 'ID + 1
	number as integer 'positive to consume, negative to acquire
End Type

Type AttackDataChain
	atk_id as integer 'ID+1, 0=None
	rate as integer
	mode as integer
	val1 as integer
	val2 as integer
	'--bitsets
	must_know as bool
	no_delay as bool
	nonblocking as bool
	dont_retarget as bool
End Type

Type AttackElementCondition
	type as CompType  'Only compNone, compLt, compGt supported!
	value as single
End Type

Type AttackData
	id as integer 'should only be set when loaded!
	name as string
	description as string
	picture as integer
	pal as integer
	override_wep_pic as bool 'YES if wep_picture and wep_pal are to be used.
	wep_picture as integer
	wep_pal as integer
	wep_handle(1) as XYPair 'Handle offset ONLY applies when override_wep_pic is YES. Ignored when the hero's equipped weapon is used
	anim_pattern as integer
	targ_class as integer
	targ_set as integer
	damage_math as integer
	aim_math as integer
	base_atk_stat as integer
	base_def_stat as integer
	mp_cost as integer
	hp_cost as integer
	money_cost as integer
	extra_damage as integer
	attacker_anim as integer
	attack_anim as integer
	attack_delay as integer 'in ticks
	turn_delay as integer 'in turns
	hits as integer
	targ_stat as integer
	prefer_targ as integer
	prefer_targ_stat as integer
	caption_time as integer
	caption as string
	caption_delay as integer
	tagset(1) as AttackDataTag
	item(2) as AttackDataItem
	elemental_fail_conds(maxElements - 1) as AttackElementCondition
	sound_effect as integer ' ID + 1
	chain as AttackDataChain
	elsechain as AttackDataChain
	instead as AttackDataChain
	learn_sound_effect as integer ' ID + 1
	transmog_enemy as integer ' ID +1, 0 no change
	transmog_hp as integer
	transmog_stats as integer
	'----Bitsets----
	cure_instead_of_harm as bool
	divide_spread_damage as bool
	absorb_damage as bool
	unreversable_picture as bool
	can_steal_item as bool
	elemental_damage(maxElements - 1) as bool
	cannot_target_enemy_slot(7) as bool
	cannot_target_hero_slot(3) as bool
	ignore_extra_hits as bool
	erase_rewards as bool
	show_damage_without_inflicting as bool
	store_targ as bool
	delete_stored_targ as bool
	automatic_targ as bool
	show_name as bool
	do_not_display_damage as bool
	reset_targ_stat_before_hit as bool
	allow_cure_to_exceed_maximum as bool
	useable_outside_battle as bool
	obsolete_damage_mp as bool
	do_not_randomize as bool
	damage_can_be_zero as bool
	force_run as bool
	force_victory as bool
	force_battle_exit as bool
	mutable as bool
	fail_if_targ_poison as bool
	fail_if_targ_regen as bool
	fail_if_targ_stun as bool
	fail_if_targ_mute as bool
	percent_damage_not_set as bool
	check_costs_as_weapon as bool
	no_chain_on_failure as bool
	reset_poison as bool
	reset_regen as bool
	reset_stun as bool
	reset_mute as bool
	cancel_targets_attack as bool
	not_cancellable_by_attacks as bool
	no_spawn_on_attack as bool
	no_spawn_on_kill as bool
	check_costs_as_item as bool
	recheck_costs_after_delay as bool
	targ_does_not_flinch as bool
	do_not_exceed_targ_stat as bool
	nonblocking as bool
End Type

'An item in a hero's spell list definition (actual spell lists in spell() array of integers)
Type SpellList
	attack as integer   'attack id+1, 0 for unused
	learned as integer  '0 if learnable from an item, or level+1 if learnt at level
End Type

Type HeroDef
	name as string
	sprite as integer
	sprite_pal as integer
	walk_sprite as integer
	walk_sprite_pal as integer
	portrait as integer
	portrait_pal as integer
	def_level as integer
	def_weapon as integer
	Lev0 as stats
	LevMax as stats
	spell_lists(3,23) as SpellList
	elementals(maxElements - 1) as single
	bits(2) as integer
	list_name(3) as string
	list_type(3) as integer
	have_tag as integer
	alive_tag as integer
	leader_tag as integer
	active_tag as integer
	max_name_len as integer
	hand_pos(1) as XYPair
	reld as Reload.NodePtr
	
	Declare Destructor ()  'defined in common.bas
End Type

'This caches the tags needed by evalherotag/tag_is_special
TYPE HeroTagsCache
	have_tag as integer
	alive_tag as integer
	leader_tag as integer
	active_tag as integer
END TYPE

'This is part of the UDT for items, which hasn't been written yet
'It caches the tags needed by evalitemtag/tag_is_special
TYPE ItemTagsCache
	have_tag         as integer
	in_inventory_tag as integer
	is_equipped_tag  as integer
	is_actively_equipped_tag as integer
END TYPE

TYPE EnemyStealDef
  thievability as integer
  item as integer
  item_rate as integer
  rare_item as integer
  rare_item_rate as integer
END TYPE

TYPE EnemyRewardDef
  gold as long
  exper as long
  item as integer
  item_rate as integer
  rare_item as integer
  rare_item_rate as integer
END TYPE

TYPE EnemySpawnDef
  how_many as integer
  on_death as integer                       'id+1, 0=none
  non_elemental_death as integer            'id+1, 0=none
  when_alone as integer                     'id+1, 0=none
  non_elemental_hit as integer              'id+1, 0=none
  elemental_hit(maxElements - 1) as integer 'id+1, 0=none
END TYPE

TYPE EnemyDef
  name as string
  steal as EnemyStealDef
  reward as EnemyRewardDef
  dissolve as integer
  dissolve_length as integer
  death_sound as integer ' id+1, 0=default, -1=none
  cursor_offset as XYPair
  pic as integer
  pal as integer
  size as integer
  stat as stats
  elementals(maxElements - 1) as single
  spawn as EnemySpawnDef
  regular_ai(4) as integer     'id+1, 0=none
  desperation_ai(4) as integer 'id+1, 0=none
  alone_ai(4) as integer       'id+1, 0=none
  elem_counter_attack(maxElements - 1) as integer 'id+1, 0=none
  stat_counter_attack(11) as integer 'id+1, 0=none
  bequest_attack as integer    'id+1, 0=none
  '--bitsets
  harmed_by_cure as bool
  mp_idiot       as bool  'for turn loss when using MP-consuming attacks after MP runs out
  is_boss        as bool
  unescapable    as bool
  die_without_boss    as bool
  flee_instead_of_die as bool
  enemy_untargetable  as bool
  hero_untargetable   as bool
  death_unneeded as bool
  never_flinch   as bool
  ignore_for_alone    as bool
END TYPE

TYPE FormationSlot
  id as integer    '-1: none
  pos as XYPair
END TYPE

TYPE Formation
  slots(7) as FormationSlot
  music as integer              '-1: none, -2: same as map
  background as integer
  background_frames as integer  'always >= 1 (no animation if == 1)
  background_ticks as integer
END TYPE

TYPE FormationSet
  frequency as integer
  tag as integer                'required tag
  formations(19) as integer     '-1: unused
END TYPE

TYPE TextBox
  text(7) as string
  instead_tag as integer
  instead     as integer
  settag_tag  as integer
  settag1     as integer
  settag2     as integer
  battle_tag  as integer
  battle      as integer
  shop_tag    as integer
  shop        as integer
  hero_tag    as integer
  hero_addrem as integer
  hero_swap   as integer
  hero_lock   as integer
  after_tag   as integer
  after       as integer
  money_tag   as integer
  money       as integer
  door_tag    as integer
  door        as integer
  item_tag    as integer
  item        as integer
  menu_tag    as integer
  menu        as integer
  choice_enabled as bool
  no_box      as bool
  opaque      as bool
  restore_music as bool
  choice(1)   as string
  choice_tag(1) as integer
  vertical_offset as integer ' in 4-pixel increments
  shrink      as integer     ' in 4-pixel increments, -1 is "Auto"
  textcolor   as integer     ' 0=default
  boxstyle    as integer
  backdrop    as integer     ' +1
  music       as integer     ' +1
  portrait_box  as integer
  portrait_type as integer
  portrait_id   as integer
  portrait_pal  as integer
  portrait_pos  as XYPair
  sound_effect as integer    ' +1, 0 means none
  stop_sound_after as bool
  backdrop_trans as bool
END TYPE

TYPE VehicleData
  name           as string
  speed          as integer
  random_battles as integer
  use_button     as integer
  menu_button    as integer
  riding_tag     as integer
  on_mount       as integer
  on_dismount    as integer
  override_walls as integer
  blocked_by       as integer
  mount_from     as integer
  dismount_to    as integer
  elevation      as integer
  '--bitsets
  pass_walls     as bool
  pass_npcs      as bool
  enable_npc_activation as bool
  enable_door_use       as bool
  do_not_hide_leader    as bool
  do_not_hide_party     as bool
  dismount_ahead        as bool
  pass_walls_while_dismounting as bool
  disable_flying_shadow as bool
END TYPE

TYPE VehicleState
  active    as bool 'Is mounting/in/dismounting. If this is false, the rest is garbage
  id        as integer 'vehicle defintion id that is loaded into .dat
  dat       as VehicleData
  npc       as integer 'npc reference number
  old_speed as integer 'hero speed before mount
  mounting  as bool
  rising    as bool
  falling   as bool
  init_dismount as bool
  trigger_cleanup as bool
  ahead     as bool
END TYPE

TYPE SpriteSize
 name as string
 size as XYPair
 frames as integer
 genmax as integer 'Offset in gen() where max record index is stored
 genmax_offset as integer 'if gen() actually stores num instead of max, this is -1
END TYPE

TYPE DistribState
  pkgname as string
  gamename as string
  author as string
  email as string
  website as string
  description as string
  more_description as string
  license as string
  copyright_year as string
END TYPE


#end